/*
 * Email Notify
 * Copyright: (C) 2008 by Antonio Nastasi
 * Email: sifcenter (at) gmail.it
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "plasma-emailnotify.h"

#include <QPainter>
#include <QFontMetrics>
#include <QSizeF>
#include <QString>
#include <KStandardDirs>
#include <KAction>
#include <KProcess>
#include <KMessageBox>
#include <plasma/svg.h>
#include <plasma/theme.h>
#include <plasma/containment.h>


EmailNotify::EmailNotify(QObject *parent, const QVariantList &args)
    : Plasma::Applet(parent, args),
    m_icon("emailnotify"),
    config_(0),
    timer_(0),
    media_(0),
    configDialog_(0),
    account_(0),
    listActions_(0)
{
  setHasConfigurationInterface(true);
  setBackgroundHints( DefaultBackground );
  resize(200, 200);
  
  if( m_icon.isNull() )
  {
    // Loading error
    setFailedToLaunch( true, "Loading error!" );
    exit(-1);
  }
}



void EmailNotify::updater()
{
  kDebug() << "Updater";
  setText( text_ );
  timer_->start( 1000 );
}



EmailNotify::~EmailNotify()
{
  if( hasFailedToLaunch() )
  {
    qDebug() << "failed to launch";
  }
  else
  {
    emailChecker_->exit();
    delete configDialog_;
    delete media_;
    delete timer_;
    delete account_;
    delete listActions_;
    //delete emailChecker_;
  }
  kDebug() << "DESTROYED";
}



/* Open the configure dialog */
void EmailNotify::showConfigurationInterface()
{
  // if configDialog is null pointer, create it!
  if( configDialog_ == 0 )
  {
    configDialog_ = new ConfigDialog( generalGroup_ );
    Q_ASSERT( configDialog_ != 0 );
    connect( configDialog_, SIGNAL( configUpdated() ), account_, SLOT( slotReadConfig() ) );
  }

  // show configure dialog
  configDialog_->show();
}



void EmailNotify::playSound()
{
  kDebug() << "Try to play sound";
  if( ( account_->getSoundFile() == "(Nothing)" ) || account_->getSoundFile().isEmpty() )
  {
    return;
  }

  QString file( KGlobal::dirs()->locate( "sound", account_->getSoundFile() ) );
  if( file.isEmpty() )
  {
    return;
  }

  Q_ASSERT( media_ != 0 );
  media_->setCurrentSource(file);
  media_->play();
  kDebug() << "Playing sound";
}



void EmailNotify::init()
{
  // Set the configuration
  config_ = new KConfig( "emailnotifyrc" );
  Q_ASSERT( config_ != 0  );
  generalGroup_ = KConfigGroup( config_, "General" );

  // Set the media object
  media_ = Phonon::createPlayer(Phonon::MusicCategory);
  Q_ASSERT( media_ != 0 );

  // Create timer for check emails
  timer_ = new QTimer( this );
  Q_ASSERT( timer_ != 0 );
  connect ( timer_, SIGNAL( timeout() ), this, SLOT( slotCheckEmails() ) );

  emailChecker_ = new EmailChecker( this );
  Q_ASSERT( emailChecker_ != 0 );
  connect( emailChecker_, SIGNAL( updatedText( QString ) ), this, SLOT( setText( QString ) ) );

  // Set information for the current account
  account_ = new Account( generalGroup_ );
  Q_ASSERT( account_ != 0 );
  connect( account_, SIGNAL( currentEmailsChanged() ), this, SLOT( slotEmailsChanged() ) );
  connect( account_, SIGNAL( accountUpdated()       ), this, SLOT( updater()           ) );

  // Play a sound when email is received
  connect( account_, SIGNAL( newEmailReceived()     ), this, SLOT( playSound() ) );

  account_->slotReadConfig();
}



void EmailNotify::slotEmailsChanged()
{
  // At account settings the emails count is changed
  if( account_->getShortCaption() )
  {
    // Set short caption
    text_ = QString::number( account_->getCurrentEmails(), 10 );
  }
  else
  {
    // Set long caption
    text_ = "You have " +  QString::number( account_->getCurrentEmails(), 10 ) + " new messages";
  }

  QGraphicsItem::setToolTip("");
  setText( text_ );
}



void EmailNotify::slotCheckEmails()
{
  // Check if the config is complete, else put the alert message
  if( account_->getServer().isEmpty() || account_->getPort() == 0 ||
      account_->getProtocol().isEmpty() || account_->getLogin().isEmpty()
      || account_->getPassword().isEmpty() )
  {
    KMessageBox::error( NULL, "Configure me, please!", "No configuration" );
    setText( "Configure me, please!" );

    // Stop the timer, so this will be called when config is updated
    timer_->stop();

    kDebug() << "Timer stopped..missing config!";
    return;
  }

  // Set the current account into email checker
  emailChecker_->setAccount( account_ );

  // Check emails
  kDebug() << "run checkemails!";
  if( emailChecker_->isRunning() )
  {
    kDebug() << "Warning: thread is still running..stopping";
    emailChecker_->closeConnection();
    return;
  }

  emailChecker_->start();

  // Set the timer to personal choose
  if( account_->getInterval() != 0 )
  {
    timer_->setInterval( account_->getInterval() * 1000 );
    kDebug() << "Timer interval set to:" << timer_->interval();
  }
}



void EmailNotify::setText( QString text )
{
  kDebug() << "called!";
  if( account_->getShortCaption() )
  {
    QGraphicsItem::setToolTip( text );
  }
  else
  {
    text_ = text;
  }

  update();
}



void EmailNotify::paintInterface(QPainter *p,
        const QStyleOptionGraphicsItem */*option*/, const QRect &contentsRect )
{
  kDebug() << "Updating interface...";

  // Set default alignment
  int alignment = Qt::AlignBottom | Qt::AlignHCenter;

  p->setRenderHint( QPainter::SmoothPixmapTransform ) ;
  p->setRenderHint( QPainter::Antialiasing );

  // Grep and set color font configuration
  if( account_->getFontColor().isValid() )
  {
    p->setPen( account_->getFontColor() );
  }
  else
  {
    // Default color
    p->setPen( Qt::white );
  }

  // Set font
  p->setFont( account_->getFont() );

  // If containment is Panel, fix the size and force short caption
  if( containment()->containmentType() == Plasma::Containment::PanelContainment )
  {
    // If long caption is currently setted force to switch to short mode
    if( ! account_->getShortCaption() )
    {
      account_->setShortCaption( true );
    }
  }

  // Check the preferences for short caption: position and type
  if( account_->getShortCaption() )
  {
    switch( account_->getPosition() )
    {
      case 0:
        alignment = Qt::AlignTop | Qt::AlignRight;
        break;
      case 1:
        alignment = Qt::AlignTop | Qt::AlignLeft;
        break;
      case 2:
        alignment = Qt::AlignBottom | Qt::AlignRight;
        break;
      case 3:
        alignment = Qt::AlignBottom | Qt::AlignLeft;
        break;
    }
  }

  p->drawPixmap( 0, 0, m_icon.pixmap( ( int ) contentsRect.width(), ( int ) contentsRect.width() ) );
  p->save();
  p->drawText( contentsRect,  alignment, text_ );
  p->restore();
}



// Add open client menu'
QList<QAction *> EmailNotify::contextualActions()
{
  if( listActions_ == 0 )
  {
    kDebug() << "Creating new contextual menu actions";
    // Create actions menu
    listActions_ = new QList<QAction*>();

    KAction *action = new KAction( KIcon( "email" ) ,"Open email client" ,this );
    listActions_->append( action );
    connect( action, SIGNAL( triggered( bool ) ), this, SLOT( slotOpenEmailClient() ) );

    action = new KAction( KIcon( "edit-redo" ) ,"Force update" ,this );
    listActions_->append( action );
    connect( action, SIGNAL( triggered( bool ) ), this, SLOT( updater() ) );
  }

  return *listActions_;
}



// Open client email
void EmailNotify::slotOpenEmailClient() const
{
  if( ( ! account_->getClientEmail().isEmpty() ) && ( account_->getClientEmail() != "(Nothing)" ) )
  {
    KProcess::execute( account_->getClientEmail() );
  }
  else
  {
    KMessageBox::information( NULL, "No email client setted", "Information" );
  }
}



void EmailNotify::constraintsUpdated( Plasma::Constraints /* constraints */ )
{
  update();
}

#include "plasma-emailnotify.moc"
